home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / freemacs.arc / IBM.ASM < prev    next >
Assembly Source File  |  1988-03-17  |  15KB  |  776 lines

  1. ;History:26,1
  2.     page    ,132
  3.  
  4. comment /
  5.  
  6.     Porting EMACS and Percival to MS-DOS computers other than the Z-100:
  7.  
  8. This entire file (Z-100.ASM) needs to be re-written, since it contains
  9. all the Z-100 dependencies.  The following conventions must be maintained:
  10.   1) Never leave this module with DF=1.
  11.   2) Never destroy ES.
  12.   3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
  13.   4) Return NC if a routine succeeds, or fulfills its goals.
  14.  
  15. /
  16.     .xlist
  17.     include    memory.def
  18.  
  19.  
  20. data    segment    byte public
  21.  
  22.     public    max_screen_line
  23. max_screen_line    db    22    ;number of last text row on screen.
  24.  
  25.  
  26.     public    scan_lines_per_char
  27. scan_lines_per_char    db    8
  28.  
  29.  
  30. key_names    label    byte
  31.     db    ',','Comma',0
  32.     db    '(','LPar',0
  33.     db    ')','RPar',0
  34.     db    7fh,'Delete',0
  35.  
  36.     db    -1,'Timeout',0
  37.     db    -2,'Left Down',0        ;mouse button key names.
  38.     db    -3,'Right Down',0
  39.     db    -4,'Left Up',0
  40.     db    -5,'Right Up',0
  41.     db    -6,'Middle Down',0
  42.     db    -7,'Middle Up',0
  43.  
  44.     db    0
  45.  
  46.  
  47. key_others    label    byte
  48.     db    14,'Back Space',0
  49.     db    15,'Tab',0
  50.     db    28,'Return',0
  51.     db    1,'Escape',0
  52.  
  53.     db    0
  54.  
  55.  
  56. key_table    label    byte
  57.     db    3,'C-@',0
  58.  
  59.     db    15,'Back Space',0
  60.  
  61.     db    71,'Home',0
  62.     db    79,'End',0
  63.     db    73,'Pg Up',0
  64.     db    81,'Pg Dn',0
  65.     db    75,'Left Arrow',0
  66.     db    77,'Right Arrow',0
  67.     db    72,'Up Arrow',0
  68.     db    80,'Down Arrow',0
  69.     db    82,'Ins',0
  70.     db    83,'Del',0
  71.  
  72.     db    59,'F1',0
  73.     db    60,'F2',0
  74.     db    61,'F3',0
  75.     db    62,'F4',0
  76.     db    63,'F5',0
  77.     db    64,'F6',0
  78.     db    65,'F7',0
  79.     db    66,'F8',0
  80.     db    67,'F9',0
  81.     db    68,'F10',0
  82.  
  83.     db    84,'F1',0
  84.     db    85,'F2',0
  85.     db    86,'F3',0
  86.     db    87,'F4',0
  87.     db    88,'F5',0
  88.     db    89,'F6',0
  89.     db    90,'F7',0
  90.     db    91,'F8',0
  91.     db    92,'F9',0
  92.     db    93,'F10',0
  93.  
  94.     db    94,'F1',0
  95.     db    95,'F2',0
  96.     db    96,'F3',0
  97.     db    97,'F4',0
  98.     db    98,'F5',0
  99.     db    99,'F6',0
  100.     db    100,'F7',0
  101.     db    101,'F8',0
  102.     db    102,'F9',0
  103.     db    103,'F10',0
  104.  
  105.     db    104,'F1',0
  106.     db    105,'F2',0
  107.     db    106,'F3',0
  108.     db    107,'F4',0
  109.     db    108,'F5',0
  110.     db    109,'F6',0
  111.     db    110,'F7',0
  112.     db    111,'F8',0
  113.     db    112,'F9',0
  114.     db    113,'F10',0
  115.  
  116.     db    119,'Home',0
  117.     db    117,'End',0
  118.     db    132,'Pg Up',0
  119.     db    118,'Pg Dn',0
  120.     db    115,'Left Arrow',0
  121.     db    116,'Right Arrow',0
  122.     db    160,'Up Arrow',0
  123.     db    164,'Down Arrow',0
  124.     db    165,'Ins',0
  125.     db    166,'Del',0
  126.  
  127.     db    129,'0',0        ;alt top row
  128.     db    120,'1',0
  129.     db    121,'2',0
  130.     db    122,'3',0
  131.     db    123,'4',0
  132.     db    124,'5',0
  133.     db    125,'6',0
  134.     db    126,'7',0
  135.     db    127,'8',0
  136.     db    128,'9',0
  137.     db    130,'-',0
  138.     db    131,'=',0
  139.  
  140.     db    16,'q',0        ;alt second row
  141.     db    17,'w',0
  142.     db    18,'e',0
  143.     db    19,'r',0
  144.     db    20,'t',0
  145.     db    21,'y',0
  146.     db    22,'u',0
  147.     db    23,'i',0
  148.     db    24,'o',0
  149.     db    25,'p',0
  150.  
  151.     db    30,'a',0        ;alt third row
  152.     db    31,'s',0
  153.     db    32,'d',0
  154.     db    33,'f',0
  155.     db    34,'g',0
  156.     db    35,'h',0
  157.     db    36,'j',0
  158.     db    37,'k',0
  159.     db    38,'l',0
  160.  
  161.     db    44,'z',0        ;alt fourth row
  162.     db    45,'x',0
  163.     db    46,'c',0
  164.     db    47,'v',0
  165.     db    48,'b',0
  166.     db    49,'n',0
  167.     db    50,'m',0
  168.  
  169.     db    0,'Unknown',0
  170.  
  171.  
  172. one_key_string    db    ?,0
  173.  
  174. ctrl_flag    equ    1
  175. left_flag    equ    2
  176. right_flag    equ    4
  177. alt_flag    equ    8
  178. shift_flags    db    ?
  179.  
  180.  
  181. key_buffer    label    byte        ;this is where we put the ASCII
  182.     db    26 dup(?)        ;  representation of the key.
  183.  
  184.  
  185.     extrn    inversing: word        ;if we're inverse videoing.
  186.  
  187.     public    color
  188. color    db    07h            ;xbbbxfff bbb=background, fff=fore.
  189.  
  190. font_8_table    label    byte
  191.     db    007h            ;visi space
  192.     db    004h            ;visi tab
  193.     db    ?            ;del
  194.     db    ?            ;eof
  195.     db    ?            ;visi newline
  196.     db    01ah            ;right arrow
  197.     db    ?            ;random char.
  198.     db    01fh            ;visible newline.
  199.  
  200. ;a character must be chosen which causes the idling string to be reloaded.
  201. ;  this one is ctrl-prtsc.
  202.     public    breakchar
  203. breakchar    dw    114*256 + 0
  204.  
  205. data    ends
  206.  
  207.  
  208. code    segment    byte public
  209.     assume    cs:code, ds:data, es:nothing
  210. ;all of the code in this segment is called with the above assumes.
  211.  
  212.  
  213. their_keybd    dd    ?        ;-> their keyboard handler.
  214.  
  215.     public    init_entry
  216. init_entry:
  217.     mov    ax,0*256 + 3        ;25x80 color.
  218.     int    10h
  219.  
  220.     push    es
  221.     mov    ax,3509h
  222.     int    21h
  223.     mov    word ptr their_keybd+0,bx
  224.     mov    word ptr their_keybd+2,es
  225.     pop    es
  226.  
  227.     push    ds
  228.     mov    ax,cs
  229.     mov    ds,ax
  230.     mov    dx,offset our_keybd
  231.     mov    ax,2509h
  232.     int    21h
  233.     pop    ds
  234.  
  235.     ret
  236.  
  237.  
  238.     public    uninit_exit
  239. uninit_exit:
  240. ;called when exiting.  May destroy any but seg-regs.
  241.     mov    dh,0            ;put the cursor on the last scrollable line.
  242.     mov    dl,max_screen_line
  243.     inc    dl
  244.     call    position_cursor
  245.  
  246.     push    ds
  247.     lds    dx,their_keybd
  248.     mov    ax,2509h
  249.     int    21h
  250.     pop    ds
  251.  
  252.     ret
  253.  
  254.  
  255. bios_seg    segment at 40h
  256.     org    1ah
  257. buffer_head    dw    ?
  258. buffer_tail    dw    ?
  259. kb_buffer    dw    16 dup(?)
  260. kb_buffer_end    label    word
  261. bios_seg    ends
  262.  
  263.  
  264. our_keybd:
  265.     push    ax
  266.     push    bx
  267.     push    ds
  268.     mov    ax,bios_seg
  269.     mov    ds,ax
  270.     assume    ds:bios_seg
  271.     in    al,60h            ;get the current keycode.
  272.     mov    ah,al            ;remember the keycode.
  273.     and    al,7fh            ;forget the shift.
  274.     cmp    al,1dh            ;ctrl
  275.     je    our_keybd_2
  276.     cmp    al,2ah            ;left shift
  277.     je    our_keybd_2
  278.     cmp    al,36h            ;right shift
  279.     je    our_keybd_2
  280.     cmp    al,38h            ;alt
  281.     jne    our_keybd_1
  282. our_keybd_2:
  283.     mov    al,80h            ;make a 80h with special scan codes.
  284.     mov    bx,buffer_tail
  285.     add    bx,2
  286.     cmp    bx,offset kb_buffer_end
  287.     jne    our_keybd_3
  288.     mov    bx,offset kb_buffer
  289. our_keybd_3:
  290.     cmp    bx,buffer_head        ;any room?
  291.     je    our_keybd_1        ;  no.
  292.     xchg    buffer_tail,bx        ;save the new, get the old.
  293.     mov    [bx],ax            ;store the key at the old ptr.
  294. our_keybd_1:
  295.     pop    ds
  296.     pop    bx
  297.     pop    ax
  298.     jmp    their_keybd
  299.  
  300.     assume    ds:data
  301.  
  302.  
  303.     public    check_for_key
  304. check_for_key:
  305. ;return zr,ax=0 if no key is waiting.
  306. ;return nz,ax=key if a key is waiting, but don't input the key yet.
  307.     mov    ah,1            ;check for a key.
  308.     int    16h
  309.     jne    check_for_key_1        ;go if we got a key.
  310.     mov    ax,0            ;return ax=0 if we didn't.
  311.     ret
  312. check_for_key_1:
  313.     call    detect_shifts
  314.     jne    check_for_key_2
  315.     mov    ah,0            ;must have been a shift key -
  316.     int    16h            ;  get rid of it.
  317.     xor    ax,ax
  318. check_for_key_2:
  319.     ret
  320.  
  321.  
  322.     public    get_key_value
  323. get_key_value:
  324. ;exit with ax=keycode.
  325.     mov    ah,0
  326.     int    16h
  327.     call    detect_shifts        ;remove shift bytes from the buffer.
  328.     je    get_key_value
  329.     ret
  330.  
  331.  
  332. detect_shifts:
  333. ;enter with ax=keycode.
  334. ;exit with zr,ax=0 if it was a shift code.
  335. ;exit with nz,ax=key if a real key.
  336.     cmp    al,80h            ;our special code?
  337.     jne    detect_shifts_1        ;no - must be a real key.
  338. detect_shifts_5:
  339.     mov    al,ctrl_flag
  340.     cmp    ah,1dh            ;ctrl down
  341.     je    detect_shifts_6
  342.     cmp    ah,1dh+80h        ;ctrl up
  343.     je    detect_shifts_6
  344.     mov    al,left_flag
  345.     cmp    ah,2ah            ;left shift down
  346.     je    detect_shifts_6
  347.     cmp    ah,2ah+80h        ;left shift up
  348.     je    detect_shifts_6
  349.     mov    al,right_flag
  350.     cmp    ah,36h            ;right shift down
  351.     je    detect_shifts_6
  352.     cmp    ah,36h+80h        ;right shift up
  353.     je    detect_shifts_6
  354.     mov    al,alt_flag
  355.     cmp    ah,38h            ;alt down
  356.     je    detect_shifts_6
  357.     cmp    ah,38h+80h        ;alt up
  358.     jne    detect_shifts_7        ;unknown, but not a key.
  359. detect_shifts_6:
  360.     or    shift_flags,al        ;assume down
  361.     or    ah,ah            ;down or up?
  362.     jns    detect_shifts_7        ;go if down
  363.     not    al            ;up - make inverse flag.
  364.     and    shift_flags,al        ;  and turn the bit off.
  365. detect_shifts_7:
  366.     xor    ax,ax            ;return zero.
  367. detect_shifts_1:
  368.     ret
  369.  
  370.  
  371.     public    decode_key
  372. decode_key:
  373. ;enter with ax=key value.
  374. ;exit with si,cx -> the key's name in ASCII.
  375.     mov    di,offset key_buffer
  376.  
  377.     or    al,al            ;extended function key?
  378.     je    decode_key_5
  379.  
  380.     push    ax
  381.     mov    si,offset key_others
  382.     call    decode_search        ;search for the scan code names.
  383.     pop    ax
  384.     jne    decode_key_1
  385.  
  386.     mov    ah,al
  387.     mov    si,offset key_names
  388.     call    decode_search        ;search for the literal names.
  389.     jne    decode_key_7        ;copy it in, but don't do shifts.
  390.     mov    al,ah
  391.  
  392.     cmp    al,' '            ;control char?
  393.     jae    decode_key_6        ;no
  394.     add    al,'@'            ;yes - convert into letter.
  395.     mov    one_key_string,al
  396.     mov    si,offset one_key_string
  397.     jmp    decode_key_1
  398. decode_key_6:
  399.     mov    one_key_string,al
  400.     mov    si,offset one_key_string
  401.     cmp    al,' '
  402.     je    decode_key_1        ;interpret shift for space bar.
  403.     call    decode_meta        ;don't interpret shift key for printables.
  404.     call    decode_ctrl
  405.     jmp    decode_key_7
  406.  
  407. decode_key_5:
  408.     mov    si,offset key_table    ;search for the extended functions.
  409.     call    decode_search
  410. decode_key_1:
  411.     call    decode_meta
  412.     call    decode_ctrl
  413.     call    decode_shift
  414. decode_key_7:
  415.     lodsb                ;copy to the next null.
  416.     stosb
  417.     or    al,al
  418.     jne    decode_key_7
  419.     dec    di            ;don't include the null.
  420.     mov    si,offset key_buffer
  421.     mov    cx,di
  422.     sub    cx,si
  423.     ret
  424.  
  425.  
  426. decode_ctrl:
  427.     test    shift_flags,ctrl_flag
  428.     je    decode_ctrl_1
  429.     mov    ax,'C' + '-'*256
  430.     stosw
  431. decode_ctrl_1:
  432.     ret
  433.  
  434.  
  435. decode_shift:
  436.     test    shift_flags,left_flag + right_flag
  437.     je    decode_shift_1
  438.     mov    ax,'S' + '-'*256
  439.     stosw
  440. decode_shift_1:
  441.     ret
  442.  
  443. decode_meta:
  444.     test    shift_flags,alt_flag
  445.     je    decode_meta_1
  446.     mov    ax,'M' + '-'*256
  447.     stosw
  448. decode_meta_1:
  449.     ret
  450.  
  451.  
  452. decode_search:
  453. ;enter with ah=key to search for, si->table.
  454. ;exit with al=key, nz if found, al=0, zr if not found.
  455.     lodsb
  456.     or    al,al            ;end of table?
  457.     je    decode_search_2        ;yes - try shifted values.
  458.     cmp    al,ah            ;is this the key?
  459.     je    decode_search_2        ;yes.
  460. decode_search_1:
  461.     lodsb                ;skip to the next null.
  462.     or    al,al
  463.     jne    decode_search_1
  464.     jmp    decode_search
  465. decode_search_2:
  466.     or    al,al
  467.     ret
  468.  
  469.  
  470.     public    ring_the_bell
  471. ring_the_bell:
  472.     mov    bx,6779
  473.     call    beep
  474.     ret
  475.  
  476.  
  477. ;Beep procedure count values
  478. ;---------------------------
  479. ;To generate a given freqency note out of the speaker with the Beep procedure
  480. ;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
  481. ;must be loaded with a value such that the 8253 input clock frequency
  482. ;(1.19318 MHz) divided by the count figure equals the audio frequency.
  483. ;enter with bx=count figure for frequency to be generated.
  484. beep:
  485.     mov    al,0b6h        ; Channel 2, LSB then MSB, Square Wave, Binary
  486.     out    43h,al        ; Program 8253 command register
  487.     mov    ax,bx        ; Get the frequency to be generated
  488.     out    42h,al        ; Load Channel 2 count register LSB
  489.     mov    al,ah
  490.     out    42h,al        ; Load Channel 2 count register MSB
  491.     in    al,61h        ; Read settings from 8255 PPI I/O Port "PB"
  492.     mov    ah,al        ; Save original settings in AH
  493.     or    al,3        ; Enable Timer Channel 2 & Speaker data
  494.     out    61h,al        ; program the 8255 with new setting-speaker on
  495.     sub    cx,cx        ; Sneaky way to put 0FFFFH into CX when
  496. wait2:    loop    wait2        ; LOOP is first executed
  497.     mov    al,ah        ; Get original 8255 Port "PB" settings
  498.     out    61h,al        ; Reset port to original values-speaker off
  499.     ret
  500.  
  501.  
  502. code    ends
  503.  
  504. code    segment    byte public
  505.     assume    cs:code, ds:nothing, es:data
  506. ;all of the code in this segment is called with the above assumes.
  507.  
  508.     public    position_cursor
  509. position_cursor:
  510. ;enter with dh=col (0...80), dl=row (0..max_screen_line)
  511. ;exit with cursor set to that position.
  512.     push    si
  513.     push    di
  514.     push    bp
  515.     push    bx
  516.     xchg    dh,dl
  517.     mov    bh,0
  518.     mov    ah,2            ;set cursor position
  519.     int    10h
  520.     cld
  521.     xchg    dh,dl
  522.     pop    bx
  523.     pop    bp
  524.     pop    di
  525.     pop    si
  526.     ret
  527.  
  528.  
  529.     public    move_line
  530. move_line:
  531. ;enter with dl=source row, al=destination row.
  532.     push    ax
  533.     push    bx
  534.     push    cx
  535.     push    dx
  536.     push    si
  537.     push    di
  538.     push    bp
  539.     push    ds
  540.     push    es
  541.  
  542.     push    ax            ;compute the source byte.
  543.     mov    al,80*2
  544.     mul    dl
  545.     mov    si,ax
  546.     pop    ax
  547.  
  548.     mov    ah,80*2            ;compute the destination byte.
  549.     mul    ah
  550.     mov    di,ax
  551.  
  552.     call    get_video_seg        ;get the video card plane.
  553.     mov    ds,ax
  554.  
  555.     mov    cx,80            ;move the line.
  556.     rep    movsw
  557.  
  558.     pop    es
  559.     pop    ds
  560.     pop    bp
  561.     pop    di
  562.     pop    si
  563.     pop    dx
  564.     pop    cx
  565.     pop    bx
  566.     pop    ax
  567.     ret
  568.  
  569.  
  570.     public    clear_to_eol
  571. clear_to_eol:
  572. ;enter with dl=current row, dh=current column.
  573.     push    bx
  574.     mov    bl,80
  575.     call    clear_count
  576.     pop    bx
  577.     ret
  578.  
  579.  
  580.     public    clear_count
  581. clear_count:
  582. ;enter with dl=current row, dh=current column, bl=column to clear to.
  583.     push    ax
  584.     push    bx
  585.     push    cx
  586.     push    si
  587.     push    di
  588.     push    bp
  589.     push    es
  590. clear_count_0:
  591.     cmp    dh,bl        ;already past it?
  592.     jae    clear_count_1    ;yes.
  593.  
  594.     mov    ah,color
  595.     mov    al,' '            ;clear to the background color.
  596.     push    ax
  597.     call    get_video_ptr
  598.     pop    ax
  599.  
  600.     mov    cl,bl            ;compute the number of chars to clear.
  601.     sub    cl,dh
  602.     mov    ch,0
  603.     rep    stosw
  604.  
  605. clear_count_1:
  606.     pop    es
  607.     pop    bp
  608.     pop    di
  609.     pop    si
  610.     pop    cx
  611.     pop    bx
  612.     pop    ax
  613.     ret
  614.  
  615.  
  616. get_video_ptr:
  617. ;enter with dl=current row, dh=current column.
  618. ;return with es:di->character position.
  619.     mov    al,80            ;compute the offset of the char.
  620.     mul    dl
  621.     add    al,dh
  622.     adc    ah,0
  623.     shl    ax,1
  624.     mov    di,ax
  625. get_video_seg:
  626. ;return with es,ax=video segment.
  627.     xor    ax,ax
  628.     mov    es,ax
  629.     mov    ax,0b000h
  630.     cmp    byte ptr es:[449h],7    ;b/w card?
  631.     je    get_video_seg_1        ;yes - we have the segment already.
  632.     mov    ax,0b800h        ;no - segment at b800h.
  633. get_video_seg_1:
  634.     mov    es,ax
  635.     ret
  636.  
  637.  
  638.     public    xychrout
  639. xychrout:
  640. ;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
  641.     push    ax            ;save everything that we might need.
  642.     push    bx
  643.     push    cx
  644.     push    dx
  645.     push    di
  646.     push    si
  647.     push    es
  648.     push    ds
  649.     mov    bx,es
  650.     mov    ds,bx
  651.     cmp    dh,80            ;past the right margin?
  652.     jae    xychrout_3        ;yes - don't print.
  653.     cmp    ah,0            ;font zero?
  654.     jne    xychrout_5        ;no - print specially.
  655.     mov    ah,color        ;assume no inverse video
  656.     cmp    al,20h            ;print control chars specially.
  657.     jb    xychrout_control
  658.     cmp    al,0ffh            ;print 255 specially
  659.     je    xychrout_del
  660.     jmp    short xychrout_1
  661. xychrout_control:
  662.     mov    ah,color
  663.     or    ah,10h            ;bold chars.
  664.     add    al,'@'
  665.     jmp    short xychrout_1
  666. xychrout_del:
  667.     mov    ah,color
  668.     or    ah,10h
  669.     mov    al,7fh            ;bold del.
  670.     jmp    short xychrout_1
  671. xychrout_5:
  672.     mov    ah,color
  673.     mov    bx,offset font_8_table
  674.     sub    al,4dh            ;first character in font 8.
  675.     xlat
  676. xychrout_1:
  677.     mov    bx,inversing        ;set the inverse video flag.
  678.     and    bl,77h            ;strip out just the color.
  679.     xor    ah,bl            ;now flip the colors (if desired).
  680.     push    ax
  681.     call    get_video_ptr
  682.     pop    ax
  683.     stosw
  684. xychrout_3:
  685.     pop    ds
  686.     pop    es
  687.     pop    si
  688.     pop    di
  689.     pop    dx
  690.     pop    cx
  691.     pop    bx
  692.     pop    ax
  693.     ret
  694.  
  695.  
  696.     public    hardware_roll_down
  697. hardware_roll_down:
  698. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  699. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  700. ;  on the screen as the last line.
  701. ;preserve bx.
  702.   if 0
  703.     mov    dl,24            ;move the 25th line up.
  704.     mov    al,23
  705.     call    move_line
  706.  
  707.     push    bx
  708.     mov    cx,0*256 + 0
  709.     mov    dx,24*256 + 79
  710.     mov    bh,07h
  711.     mov    ax,7*256 + 1
  712.     int    10h
  713.     pop    bx
  714.     clc
  715.   else
  716.     stc
  717.   endif
  718.     ret
  719.  
  720.  
  721.     public    hardware_roll_up
  722. hardware_roll_up:
  723. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  724. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  725. ;  on the screen as the last line.
  726. ;preserve bx.
  727.   if 0
  728.     push    bx
  729.     mov    cx,0*256 + 0
  730.     mov    dx,24*256 + 79
  731.     mov    bh,07h
  732.     mov    ax,6*256 + 1
  733.     int    10h
  734.     pop    bx
  735.     mov    dl,23            ;now move the 25th line back down.
  736.     mov    al,24
  737.     call    move_line
  738.     clc
  739.   else
  740.     stc
  741.   endif
  742.     ret
  743.  
  744.  
  745.     public    block_cursor
  746. block_cursor:
  747.     mov    ah,1
  748.     mov    cx,0*256 + 7
  749.     int    10h
  750.     ret
  751.  
  752.  
  753.     public    underscore_cursor
  754. underscore_cursor:
  755.     mov    ah,1
  756.     mov    cx,6*256 + 7
  757.     int    10h
  758.     ret
  759.  
  760.  
  761.     public    set_screen_color
  762. set_screen_color:
  763. ;enter with al=fore color, ah=back color
  764.     shl    ah,1
  765.     shl    ah,1
  766.     shl    ah,1
  767.     shl    ah,1
  768.     or    al,ah
  769.     mov    color,al
  770.     ret
  771.  
  772.  
  773. code    ends
  774.  
  775.     end
  776.